package com.zhengqiangblog.core;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.codehaus.jackson.map.ObjectMapper;

public class ResultDispatcher {

	private static final Logger logger = Logger.getLogger(ResultDispatcher.class);

	public ResultDispatcher() {
		logger.info("ResultDispatcher initializing...");
	}

	public void dispatch(HttpServletRequest request, HttpServletResponse response, Result result, Model model) throws Exception {
		ResultType resultType = result.getResultType();
		switch (resultType) {
			case DISPATCHER:
				this.doDispatchOfDispatcher(request, response, result, model);
				break;
			case HTTP_HEADER:
				this.doDispatchOfHttpHeader(request, response, result, model);
				break;
			case REDIRECT:
				this.doDispatchOfRedirect(request, response, result, model);
				break;
			case REDIRECT_ACTION:
				this.doDispatchOfRedirectAction(request, response, result, model);
				break;
			case STREAM:
				this.doDispatchOfStream(request, response, result, model);
				break;
			case PLAIN_TEXT:
				this.doDispatchOfPlainText(request, response, result, model);
				break;
			case JSON:
				this.doDispatchOfJson(request, response, result, model);
				break;
			default:
		}
	}

	private void doDispatchOfDispatcher(HttpServletRequest request, HttpServletResponse response, Result result, Model model)
			throws Exception {
		RequestDispatcher requestDispatcher = request.getRequestDispatcher(result.getValue());
		requestDispatcher.forward(request, response);
	}

	private void doDispatchOfHttpHeader(HttpServletRequest request, HttpServletResponse response, Result result, Model model)
			throws Exception {
		// not supported yet.
	}

	private void doDispatchOfRedirect(HttpServletRequest request, HttpServletResponse response, Result result, Model model)
			throws Exception {
		String url = result.getValue();
		response.sendRedirect(url);
	}

	private void doDispatchOfRedirectAction(HttpServletRequest request, HttpServletResponse response, Result result, Model model)
			throws Exception {
		String namespace = model.getResultParam("namespace").toString();
		String action = model.getResultParam("action").toString();
		@SuppressWarnings("unchecked")
		HashMap<String, Object> resultParams = (HashMap<String, Object>) model.getResultParam("urlParams");
		StringBuffer sbUrl = new StringBuffer(10);
		if (!MappingHelper.isSlash(namespace)) {
			sbUrl.append(namespace);
		}
		sbUrl.append(action);
		if (resultParams != null && resultParams.size() > 0) {
			Iterator<Entry<String, Object>> iterator = resultParams.entrySet().iterator();
			Entry<String, Object> param = iterator.next();
			String paramName = param.getKey();
			String paramValue = String.valueOf(param.getValue());
			if (StringUtils.isNotBlank(paramName)) {
				sbUrl.append("?");
				sbUrl.append(paramName);
				sbUrl.append("=");
				sbUrl.append(URLEncoder.encode(paramValue, "UTF-8"));
			}
			while (iterator.hasNext()) {
				param = iterator.next();
				paramName = param.getKey();
				paramValue = String.valueOf(param.getValue());
				if (StringUtils.isNotBlank(paramName)) {
					sbUrl.append("&");
					sbUrl.append(paramName);
					sbUrl.append("=");
					sbUrl.append(URLEncoder.encode(paramValue, "UTF-8"));
				}
			}
		}
		response.sendRedirect(sbUrl.toString());
	}

	private void doDispatchOfStream(HttpServletRequest request, HttpServletResponse response, Result result, Model model) throws Exception {
		// 设置文件类型
		Object contentType = model.getResultParam("contentType");
		if (contentType != null) {
			String strContentType = contentType.toString();
			if (StringUtils.isNotBlank(strContentType)) {
				response.setContentType(strContentType);
			}
		}
		// 设置文件名称
		Object fileName = model.getResultParam("fileName");
		if (fileName != null) {
			String strFileName = fileName.toString();
			if (StringUtils.isNotBlank(strFileName)) {
				strFileName = URLEncoder.encode(strFileName, "UTF-8");
				response.addHeader("Content-Disposition", "attachment; filename=" + strFileName);
			}
		}
		Object stream = model.getResultParam("stream");
		ServletOutputStream outputStream = response.getOutputStream();
		if (stream instanceof File) { // 磁盘文件
			BufferedInputStream inputStream = null;
			try {
				File file = (File) stream;
				inputStream = new BufferedInputStream(new FileInputStream(file));
				byte[] buffer = new byte[1 * 1024 * 1024];
				int length = 0;
				while ((length = inputStream.read(buffer)) > 0) {
					outputStream.write(buffer, 0, length);
				}
			} finally {
				inputStream.close();
				outputStream.close();
			}
		} else if (stream instanceof byte[]) { // 内存中的二进制数组
			byte[] bytes = (byte[]) stream;
			try {
				outputStream.write(bytes);
			} finally {
				outputStream.close();
			}
		}
		response.flushBuffer();
	}

	private void doDispatchOfPlainText(HttpServletRequest request, HttpServletResponse response, Result result, Model model)
			throws Exception {
		Object text = model.getResultParam("text");
		response.setContentType("text/plain");
		response.getWriter().write(text.toString());
		response.flushBuffer();
	}

	private void doDispatchOfJson(HttpServletRequest request, HttpServletResponse response, Result result, Model model) throws Exception {
		Object object = model.getResultParam("json");
		ObjectMapper mapper = new ObjectMapper();
		String json = mapper.writeValueAsString(object);
		response.setContentType("text/plain");
		response.getWriter().write(json);
		response.flushBuffer();
	}

}
